package com.devperson.io.nio;

import com.devperson.io.bio.ServiceSocket.BIoServiceSocket;

import java.io.BufferedReader;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 功能描述:
 *
 * @author lixiaomeng
 * @date 2018/12/14
 */
public class NIOServiceSocket {

    public static void main(String[] args) throws Exception {

        ExecutorService executorService = Executors.newFixedThreadPool(10); // 线程池处理服务端的连接请求

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); // 打开一个服务端ServiceSocketChannel

        serverSocketChannel.configureBlocking(false); // 设置为非阻塞模式

        serverSocketChannel.bind(new InetSocketAddress(9999)); // 绑定9999端口，也就是对9999端口进行监听

        Selector selector = Selector.open(); // NIO的选择器，可以理解为客户端频道连接管理器

         // 服务端的Channel注册到对应的选择器上面
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        int selectKey = 0;
        while ((selectKey = selector.select()) > 0) {
            Iterator<SelectionKey> selectKeys =  selector.selectedKeys().iterator();
            while (selectKeys.hasNext()) {
                if (selectKeys.next().isAcceptable()) { // 服务器连接请求是接受模式，则进行处理
                    SocketChannel socketChannel = serverSocketChannel.accept(); // 等待连接
                    if (socketChannel != null) {
                        executorService.submit(new ClientAccpectHandle(socketChannel));
                    }
                }
                selectKeys.remove();
             }

        }
        executorService.shutdown();
        serverSocketChannel.close();
    }

    private static class ClientAccpectHandle implements Runnable {

        private SocketChannel socketChannel; // 客户端请求的通道

        private boolean flag = true; // 接受请求的循环处理标记

        public ClientAccpectHandle(SocketChannel socketChannel) {
            this.socketChannel = socketChannel;
        }


        @Override
        public void run() {
            ByteBuffer byteBuffer = ByteBuffer.allocate(100);
            while (flag) {
                try {
                    byteBuffer.clear();
                    int readCount = this.socketChannel.read(byteBuffer); // 想缓冲区读取客户端提交的内容
                    String readMsg = new String(byteBuffer.array(), 0 , readCount).trim();
                    String writeMsg = "[ECHO]: " + readMsg;
                    if ("byebye".equalsIgnoreCase(readMsg)) {
                        flag = false;
                        writeMsg = "拜拜了您内.....";
                    }
                    byteBuffer.clear();
                    byteBuffer.put(writeMsg.getBytes());
                    byteBuffer.flip();
                    this.socketChannel.write(byteBuffer); // 回应数据到客户端连接
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
